<!DOCTYPE html>
<html>

<head>
  <title>redux-saga</title>
  <meta charset='utf-8'>
  <link href='https://cdn.maxiang.io/res-min/themes/marxico.css' rel='stylesheet'>
  <style>
    #preview-contents {
      margin-top: -20px;
      width: 900px;
    }

    #preview-contents img {
      max-width: 600px;
    }
  </style>
</head>

<body>
  <div id='preview-contents' class='note-content'>
    <h3 id="redux-saga">redux-saga</h3>
    <blockquote>
      <p>官网：<a href="https://redux-saga.js.org/docs/About" target="_blank">https://redux-saga.js.org/docs/About</a> <br>
        中文网：<a href="https://redux-saga-in-chinese.js.org/" target="_blank">https://redux-saga-in-chinese.js.org/</a>
      </p>
      <p>redux-saga 是一个用于管理 <code>异步获取数据(副作用)</code> 的redux中间件；它的目标是让副作用管理更容易，执行更高效，测试更简单，处理故障时更容易…</p>
      <p>学习 redux-saga 之前，需要先掌握 ES6 中的 Iterator迭代器 和 Generator生成器 ！！</p>
    </blockquote>

    <h4 id="1-redux-thunk与redux-saga的比较">1. redux-thunk与redux-saga的比较</h4>
    <p><strong>redux中的数据流</strong> <br>
      action ———&gt; reducer ———&gt; state</p>
    <ul>
      <li>
        <p>action是一个纯粹对象（plain object）</p>
      </li>
      <li>
        <p>reducer是一个纯函数（和外界没有任何关系）</p>
      </li>
      <li>
        <p>都只能处理同步的操作</p>
      </li>
    </ul>
    <p><strong>redux-thunk中间件的处理流程</strong> <br>
      action1 ———&gt; middleware ———&gt; action2 ———&gt; reducer ———&gt; state </p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">/* redux-thunk中间件的部分源码 */</span>
</div><div class="hljs-line"><span class="hljs-meta">'use strict'</span>;
</div><div class="hljs-line"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createThunkMiddleware</span>(<span class="hljs-params">extraArgument</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> middleware = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">middleware</span>(<span class="hljs-params">_ref</span>) </span>{
</div><div class="hljs-line">      <span class="hljs-keyword">var</span> dispatch = _ref.dispatch,
</div><div class="hljs-line">          getState = _ref.getState;
</div><div class="hljs-line">      <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">next</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">action</span>) </span>{
</div><div class="hljs-line">          <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> action === <span class="hljs-string">'function'</span>) {
</div><div class="hljs-line">            <span class="hljs-comment">// 如果返回的action是个函数，则把函数执行「在函数中完成异步操作，用传递的dispatch单独实现派发！！」</span>
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> action(dispatch, getState, extraArgument);
</div><div class="hljs-line">          }
</div><div class="hljs-line">          <span class="hljs-keyword">return</span> next(action);
</div><div class="hljs-line">        };
</div><div class="hljs-line">      };
</div><div class="hljs-line">    };
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> middleware;
</div><div class="hljs-line">}
</div></code></pre>
    <p>弊端：异步操作分散到每一个action中；而且返回函数中的代码具备多样性！！</p>
    <p><strong>redux-saga中间件的工作流程</strong> <br>
      redux-saga中提供了一系列的api，可以去监听纯粹对象格式的action，方便单元测试！！ <br>
      action1 ———&gt; redux-saga监听 ———&gt; 执行提供的API方法 ———&gt; 返回描述对象 ———&gt; 执行异步操作 ———&gt; action2 ———&gt; reducer
      ———&gt; state </p>
    <p>这样说完，大家可能是不太理解的，那么接下来，我们去做一个案例，详细解读一下redux-saga的语法和优势！！</p>

    <hr>

    <h4 id="2-redux-saga的基础知识">2. redux-saga的基础知识</h4>
    <p><em>备注：需要先准备一套基于 “redux、redux-thunk” 实现的投票案例，我们在此基础上去修改 ！！</em></p>
    <p><strong>安装中间件</strong> <br>
      <span>$</span> npm install redux-saga <br>
      <span>$</span> yarn add redux-saga
    </p>

    <p><strong>使用中间件</strong> <br>
      store/index.js</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> { createStore, applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> createSagaMiddleware <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-saga'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> reducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./reducer'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> saga <span class="hljs-keyword">from</span> <span class="hljs-string">'./saga'</span>;
</div><div class="hljs-line"><span class="hljs-comment">// saga</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> sagaMiddleware = createSagaMiddleware();
</div><div class="hljs-line"><span class="hljs-comment">// 创建store容器</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> store = createStore(
</div><div class="hljs-line">    reducer,
</div><div class="hljs-line">    applyMiddleware(sagaMiddleware)
</div><div class="hljs-line">);
</div><div class="hljs-line"><span class="hljs-comment">// 启动saga</span>
</div><div class="hljs-line">sagaMiddleware.run(saga);
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store;
</div></code></pre>
    <p>store/action-types.js</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> VOTE_SUP = <span class="hljs-string">"VOTE_SUP"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> VOTE_OPP = <span class="hljs-string">"VOTE_OPP"</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> DEMO = <span class="hljs-string">"DEMO"</span>;
</div></code></pre>
    <p>store/reducer</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">// demoReducer</span>
</div><div class="hljs-line"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> TYPES <span class="hljs-keyword">from</span> <span class="hljs-string">'../action-types'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> _ <span class="hljs-keyword">from</span> <span class="hljs-string">'../../assets/utils'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">let</span> initial = {
</div><div class="hljs-line">    <span class="hljs-attr">num</span>: <span class="hljs-number">0</span>
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">demoReducer</span>(<span class="hljs-params">state = initial, action</span>) </span>{
</div><div class="hljs-line">    state = _.clone(state);
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> { payload = <span class="hljs-number">1</span> } = action;
</div><div class="hljs-line">    <span class="hljs-keyword">switch</span> (action.type) {
</div><div class="hljs-line">        <span class="hljs-keyword">case</span> TYPES.DEMO:
</div><div class="hljs-line">            state.num += payload;
</div><div class="hljs-line">            <span class="hljs-keyword">break</span>;
</div><div class="hljs-line">        <span class="hljs-keyword">default</span>:
</div><div class="hljs-line">    }
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> state;
</div><div class="hljs-line">};
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-comment">// index.js</span>
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { combineReducers } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> voteReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./voteReducer'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> demoReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./demoReducer'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> reducer = combineReducers({
</div><div class="hljs-line">    <span class="hljs-attr">vote</span>: voteReducer,
</div><div class="hljs-line">    <span class="hljs-attr">demo</span>: demoReducer
</div><div class="hljs-line">});
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> reducer;
</div></code></pre>
    <p>Demo.jsx组件中</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'antd'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> Demo = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Demo</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">const</span> { num } = useSelector(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.demo),
</div><div class="hljs-line">        dispatch = useDispatch();
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">fontSize:</span> <span class="hljs-attr">20</span>, <span class="hljs-attr">paddingLeft:</span> <span class="hljs-attr">10</span> }}&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            {num}</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span></span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                //基于dispatch进行派发....</span>
</div><div class="hljs-line"><span class="xml">            }}&gt;</span>
</div><div class="hljs-line"><span class="xml">            按钮</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Demo;
</div></code></pre>

    <p><strong>saga.js 工作流程</strong></p>
    <p><img longdesc="./1672344837419.png" alt="Alt text" title="" type="image/png"
        src=""
        class=""> <br>
      第一部分：创建监听器「基于saga的辅助函数」</p>
    <ul>
      <li>
        <p>take(pattern)</p>
      </li>
      <li>
        <p>takeEvery(pattern, saga, …args)</p>
      </li>
      <li>
        <p>takeLatest(pattern, saga, ..args)</p>
      </li>
      <li>
        <p>throttle(ms, pattern, saga, ..args)</p>
      </li>
      <li>
        <p>…</p>
      </li>
    </ul>
    <p>第二部分：创建执行函数「基于Effect创建器(API)」</p>
    <ul>
      <li>
        <p>put(action)</p>
      </li>
      <li>
        <p>call(fn, …args)</p>
      </li>
      <li>
        <p>fork(fn, …args)</p>
      </li>
      <li>
        <p>select(selector, …args)</p>
      </li>
      <li>
        <p>…</p>
      </li>
    </ul>

    <p><strong>每一次组件派发后发生的事情</strong> <br>
      每一次在组件中，基于 <code>dispatch(action)</code> 的时候：</p>
    <ul>
      <li>
        <p>首先会通知 reducer 执行</p>
      </li>
      <li>
        <p>然后再去通知 saga 中的监听器执行</p>
      </li>
    </ul>
    <p><img longdesc="./1672344118342.png" alt="Alt text" title="" type="image/png"
        src=""
        class=""></p>

    <p><strong>关于监听器创建的细节</strong> <br>
      组件中</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line">&lt;Button type=<span class="hljs-string">"primary"</span>
</div><div class="hljs-line">    onClick={() =&gt; {
</div><div class="hljs-line">        dispatch({
</div><div class="hljs-line">            <span class="hljs-attr">type</span>: <span class="hljs-string">"DEMO-SAGA"</span>,
</div><div class="hljs-line">            <span class="hljs-attr">payload</span>: <span class="hljs-number">10</span>
</div><div class="hljs-line">        });
</div><div class="hljs-line">    }}&gt;
</div><div class="hljs-line">    按钮
</div><div class="hljs-line">&lt;<span class="hljs-regexp">/Button&gt;</span>
</div></code></pre>
    <p>saga.js -&gt; take 函数的运用</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> TYPES <span class="hljs-keyword">from</span> <span class="hljs-string">'./action-types'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> working = <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">working</span>(<span class="hljs-params">action</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-comment">// 等价于 dispatch派发：通知reducer执行</span>
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">        <span class="hljs-attr">type</span>: TYPES.DEMO,
</div><div class="hljs-line">        <span class="hljs-attr">payload</span>: action.payload
</div><div class="hljs-line">    });
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">saga</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-comment">/* // 创建监听器，当监听到派发后，才会继续向下执行</span>
</div><div class="hljs-line"><span class="hljs-comment">    // 特征：只能监听一次</span>
</div><div class="hljs-line"><span class="hljs-comment">    // action：可以获取派发时传递的action</span>
</div><div class="hljs-line"><span class="hljs-comment">    let action = yield take("DEMO-SAGA");</span>
</div><div class="hljs-line"><span class="hljs-comment">    yield working(action); */</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 可基于循环，创建无限监听机制</span>
</div><div class="hljs-line">    <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> action = <span class="hljs-keyword">yield</span> take(<span class="hljs-string">"DEMO-SAGA"</span>);
</div><div class="hljs-line">        <span class="hljs-keyword">yield</span> working(action);
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div></code></pre>
    <p>saga.js -&gt; 其它监听器辅助函数的运用</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">const</span> working = <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">working</span>(<span class="hljs-params">action</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'AAA'</span>);
</div><div class="hljs-line">    <span class="hljs-comment">// 设置延迟函数：等待2000ms后，才会继续向下执行！！</span>
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> delay(<span class="hljs-number">2000</span>);
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">        <span class="hljs-attr">type</span>: TYPES.DEMO,
</div><div class="hljs-line">        <span class="hljs-attr">payload</span>: action.payload
</div><div class="hljs-line">    });
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">saga</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-comment">/* // 派发后，立即通知异步的working执行；</span>
</div><div class="hljs-line"><span class="hljs-comment">    // 但是在working没有处理完毕之前，所有其他的派发任务都不在处理！！</span>
</div><div class="hljs-line"><span class="hljs-comment">    while (true) {</span>
</div><div class="hljs-line"><span class="hljs-comment">        let action = yield take("DEMO-SAGA");</span>
</div><div class="hljs-line"><span class="hljs-comment">        yield working(action);</span>
</div><div class="hljs-line"><span class="hljs-comment">    } */</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">/* // 每一次派发任务都会被执行</span>
</div><div class="hljs-line"><span class="hljs-comment">    yield takeEvery("DEMO-SAGA", working); */</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">/* // 每一次派发任务都会被执行，但是会把之前没有处理完毕的干掉</span>
</div><div class="hljs-line"><span class="hljs-comment">    yield takeLatest("DEMO-SAGA", working); */</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">/* // 每一次派发的任务会做节流处理；在频繁触发的操作中，1000ms内，只会处理一次派发任务</span>
</div><div class="hljs-line"><span class="hljs-comment">    yield throttle(1000, "DEMO-SAGA", working); */</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">/* // 每一次派发的任务会做防抖处理；在频繁触发的操作中，只识别最后一次派发任务进行处理</span>
</div><div class="hljs-line"><span class="hljs-comment">    yield debounce(1000, "DEMO-SAGA", working); */</span>
</div><div class="hljs-line">};
</div></code></pre>
    <p>saga.js -&gt; yield call/select…</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> TYPES <span class="hljs-keyword">from</span> <span class="hljs-string">'./action-types'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> http <span class="hljs-keyword">from</span> <span class="hljs-string">'../api/http'</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> working = <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">working</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-comment">// 获取目前的公共状态信息</span>
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> { num } = <span class="hljs-keyword">yield</span> select(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.demo);
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 从服务器获取数据</span>
</div><div class="hljs-line">    <span class="hljs-comment">// let result = yield apply(null, http.get, ['/api/news/latest']);</span>
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> result = <span class="hljs-keyword">yield</span> call(http.get, <span class="hljs-string">'/api/news/latest'</span>);
</div><div class="hljs-line">    <span class="hljs-built_in">console</span>.log(result); <span class="hljs-comment">//从服务器获取的数据</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">        <span class="hljs-attr">type</span>: TYPES.DEMO
</div><div class="hljs-line">    });
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">saga</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> takeLatest(<span class="hljs-string">"DEMO-SAGA"</span>, working);
</div><div class="hljs-line">};
</div></code></pre>
    <p>saga.js -&gt; yield fork</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">const</span> query1 = <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">query1</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-built_in">console</span>.log(<span class="hljs-number">1</span>);
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> delay(<span class="hljs-number">2000</span>);
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">const</span> query2 = <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">query2</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-built_in">console</span>.log(<span class="hljs-number">2</span>);
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> delay(<span class="hljs-number">2000</span>);
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">const</span> working = <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">working</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-comment">/* // 串行</span>
</div><div class="hljs-line"><span class="hljs-comment">    yield call(query1);</span>
</div><div class="hljs-line"><span class="hljs-comment">    yield call(query2); */</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">/* // 并行：无阻塞调用</span>
</div><div class="hljs-line"><span class="hljs-comment">    yield fork(query1);</span>
</div><div class="hljs-line"><span class="hljs-comment">    yield fork(query2); */</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-built_in">console</span>.log(<span class="hljs-number">3</span>);
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">saga</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> takeLatest(<span class="hljs-string">"DEMO-SAGA"</span>, working);
</div><div class="hljs-line">};
</div></code></pre>

    <hr>

    <h4 id="3-基于redux-saga重写vote案例">3. 基于redux-saga重写Vote案例</h4>
    <p>组件</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> TYPES <span class="hljs-keyword">from</span> <span class="hljs-string">'../store/action-types'</span>;
</div><div class="hljs-line">...
</div><div class="hljs-line">const Vote = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Vote</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">const</span> { supNum, oppNum } = useSelector(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.vote),
</div><div class="hljs-line">        dispatch = useDispatch();
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">VoteBox</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        ...</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"footer"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span></span></span>
</div><div class="hljs-line"><span class="xml">                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                    dispatch({</span>
</div><div class="hljs-line"><span class="xml">                        type: TYPES.VOTE_SUP</span>
</div><div class="hljs-line"><span class="xml">                    });</span>
</div><div class="hljs-line"><span class="xml">                }}&gt;</span>
</div><div class="hljs-line"><span class="xml">                支持</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span></span></span>
</div><div class="hljs-line"><span class="xml">                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                    dispatch({</span>
</div><div class="hljs-line"><span class="xml">                        type: "VOTE-SUP-SAGA"</span>
</div><div class="hljs-line"><span class="xml">                    });</span>
</div><div class="hljs-line"><span class="xml">                }}&gt;</span>
</div><div class="hljs-line"><span class="xml">                异步支持</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml"></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">danger</span></span></span>
</div><div class="hljs-line"><span class="xml">                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                    dispatch({</span>
</div><div class="hljs-line"><span class="xml">                        type: TYPES.VOTE_OPP</span>
</div><div class="hljs-line"><span class="xml">                    });</span>
</div><div class="hljs-line"><span class="xml">                }}&gt;</span>
</div><div class="hljs-line"><span class="xml">                反对</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">danger</span></span></span>
</div><div class="hljs-line"><span class="xml">                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                    dispatch({</span>
</div><div class="hljs-line"><span class="xml">                        type: "VOTE-OPP-SAGA"</span>
</div><div class="hljs-line"><span class="xml">                    });</span>
</div><div class="hljs-line"><span class="xml">                }}&gt;</span>
</div><div class="hljs-line"><span class="xml">                反对异步</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">VoteBox</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Vote;
</div></code></pre>
    <p>saga.js</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> { takeLatest, put, delay } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-saga/effects'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> TYPES <span class="hljs-keyword">from</span> <span class="hljs-string">'./action-types'</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> voteSupWorking = <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">voteSupWorking</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> delay(<span class="hljs-number">2000</span>);
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">        <span class="hljs-attr">type</span>: TYPES.VOTE_SUP
</div><div class="hljs-line">    });
</div><div class="hljs-line">};
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> voteOppWorking = <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">voteOppWorking</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> delay(<span class="hljs-number">2000</span>);
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">        <span class="hljs-attr">type</span>: TYPES.VOTE_OPP
</div><div class="hljs-line">    });
</div><div class="hljs-line">};
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">saga</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> takeLatest(<span class="hljs-string">"VOTE-SUP-SAGA"</span>, voteSupWorking);
</div><div class="hljs-line">    <span class="hljs-keyword">yield</span> takeLatest(<span class="hljs-string">"VOTE-OPP-SAGA"</span>, voteOppWorking);
</div><div class="hljs-line">};
</div></code></pre>
  </div>
</body>

</html>